Appearance
ES6 出现了class 语法糖更加方便让 js 可以创建对象
- ES5 中类的写法:
javascript
function PersonType(name) {
this.name = name;
}
PersonType.prototype.sayName = function () {
console.log(this.name);
};
var personType = new PersonType('wang');
personType.sayName(); // wang
console.log('PersonType instanceof PersonType:', personType instanceof PersonType); // true
console.log('PersonType instanceof Object:', personType instanceof Object); // true
- ES6 中类的写法:
javascript
class PersonClass {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
let personClass = new PersonClass('wang');
personClass.sayName(); // wang
console.log('PersonClass instanceof PersonClass:', personClass instanceof PersonClass); // true
console.log('PersonClass instanceof Object:', personClass instanceof Object); // true
console.log('typeof PersonClass:', typeof PersonClass); // function
ES6 和 ES5 类的其他不同点
函数声明提升 vs. 类声明不可提升:
- 函数声明可以被提升,类声明类似
let
声明,不能被提升。 - 声明前使用类会导致报错。
- 函数声明可以被提升,类声明类似
自动严格模式:
- 类声明的所有代码自动运行在严格模式下。
方法不可枚举:
- 在 ES5 中需要手动指定方法不可枚举。
- ES6 类方法默认不可枚举,挂在对象原型上。
[[Construct]]
方法:- 通过
new
调用不含[[Construct]]
的方法会报错。例如箭头函数
- 通过
构造函数必须使用
new
调用:- 直接调用类的构造函数会抛出错误。
类名不可修改:
- 类声明结束后类名依然可以修改,但在类中修改会报错。
javascript
class Foo {
constructor() {
Foo = "bar"; // 这里会抛出错误
}
}
Foo = "bar"; // 类声明结束后才可以修改类名
代码优化与实现
javascript
// ES5 版本的符合以上特性的类实现
let PersonType2 = (function () {
"use strict";
const PersonType2 = function (name) {
if (typeof new.target === "undefined") {
throw new Error("Constructor must be called with new.");
}
this.name = name;
};
Object.defineProperty(PersonType2.prototype, "sayName", {
value: function () {
if (typeof new.target !== "undefined") {
throw new Error("Method cannot be called with new.");
}
console.log(this.name);
},
enumerable: false,
writable: true,
configurable: true
});
return PersonType2;
}());
const a = new PersonType2('wang');
console.log(a.name); // wang
访问器属性写法比较
- ES5 实现:
javascript
let CustomHTMLElement = (function() {
"use strict";
const CustomHTMLElement = function(element) {
if (typeof new.target === "undefined") {
throw new Error("Constructor must be called with new.");
}
this.element = element;
}
Object.defineProperty(CustomHTMLElement.prototype, "html", {
enumerable: false,
configurable: true,
get: function() {
return this.element.innerHTML;
},
set: function(value) {
this.element.innerHTML = value;
}
});
return CustomHTMLElement;
}());
- ES6 类实现:
javascript
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get html() {
return this.element.innerHTML;
}
set html(value) {
this.element.innerHTML = value;
}
}
var descriptor = Object.getOwnPropertyDescriptor(CustomHTMLElement.prototype, "html");
console.log("get" in descriptor); // true
console.log("set" in descriptor); // true
console.log(descriptor.enumerable); // false
优化建议
- 在大型项目中,使用 ES6 类可以提高代码的可读性和可维护性。
- 尽量在类的构造函数中定义所有实例属性,避免属性混乱。
- 避免在类中直接修改类名,确保代码逻辑清晰。
- 使用
Object.defineProperty
管理 ES5 访问器属性,确保代码在未来的 ES6 迁移中更简便。